﻿using PmSoft.Core.Domain.Entities;
using System.Linq.Expressions;

namespace PmSoft.Cache.Abstractions.EntityCache;

/// <summary>
/// 实体缓存服务接口，定义实体缓存管理的操作
/// </summary>
/// <typeparam name="TEntity">实体类型，必须实现 IEntity<TKey></typeparam>
/// <typeparam name="TKey">实体主键类型，不可为空</typeparam>
public interface IEntityCacheVersionService<TEntity, TKey>
	where TEntity : IEntity<TKey> where TKey : notnull
{
	/// <summary>
	/// 获取实体元数据
	/// </summary>
	IEntityMetadata Metadata { get; }

	/// <summary>
	/// 是否为分布式缓存
	/// </summary>
	bool IsDistributed { get; }

	/// <summary>
	/// 获取单个实体的缓存键（同步）
	/// </summary>
	/// <param name="entityId">实体ID</param>
	/// <returns>缓存键字符串</returns>
	string GetCacheKeyOfEntity(TKey entityId);

	/// <summary>
	/// 获取单个实体的缓存键（异步）
	/// </summary>
	/// <param name="entityId">实体ID</param>
	/// <returns>缓存键字符串</returns>
	ValueTask<string> GetCacheKeyOfEntityAsync(TKey entityId);

	/// <summary>
	/// 获取多个实体的缓存键（同步）
	/// </summary>
	/// <param name="entityIds">实体ID集合</param>
	/// <returns>ID与缓存键的映射字典</returns>
	Dictionary<string, string> GetCacheKeyOfEntitys(IEnumerable<TKey> entityIds);

	/// <summary>
	/// 获取多个实体的缓存键（异步）
	/// </summary>
	/// <param name="entityIds">实体ID集合</param>
	/// <returns>ID与缓存键的映射字典</returns>
	ValueTask<Dictionary<string, string>> GetCacheKeyOfEntitysAsync(IEnumerable<TKey> entityIds);

	/// <summary>
	/// 获取实体版本号（同步）
	/// </summary>
	/// <param name="entityId">实体ID</param>
	/// <returns>版本号</returns>
	int GetEntityVersion(TKey entityId);

	/// <summary>
	/// 获取实体版本号（异步）
	/// </summary>
	/// <param name="entityId">实体ID</param>
	/// <returns>版本号</returns>
	ValueTask<int> GetEntityVersionAsync(TKey entityId);

	//// <summary>
	/// 获取区域版本号（同步）
	/// </summary>
	/// <param name="areaKeySelector">实体属性选择表达式，用于指定区域键</param>
	/// <param name="propertyValue">属性值，若为空则返回 0</param>
	/// <returns>区域版本号，若未找到则返回 0</returns>
	int GetAreaVersion<TAreaKey>(Expression<Func<TEntity, TAreaKey>> areaKeySelector, object? propertyValue);

	/// <summary>
	/// 获取区域版本号（同步）
	/// </summary>
	/// <param name="areaKeySelector">实体属性选择表达式，用于指定区域键</param>
	/// <param name="propertyValue">属性值，若为空则返回 0</param>
	/// <returns>区域版本号，若未找到则返回 0</returns>
	ValueTask<int> GetAreaVersionAsync<TAreaKey>(Expression<Func<TEntity, TAreaKey>> areaKeySelector, object? propertyValue);

	/// <summary>
	/// 获取全局版本号（同步）
	/// </summary>
	/// <returns>全局版本号</returns>
	int GetGlobalVersion();

	/// <summary>
	/// 获取全局版本号（异步）
	/// </summary>
	/// <returns>全局版本号</returns>
	ValueTask<int> GetGlobalVersionAsync();

	/// <summary>
	/// 递增全局版本号（同步）
	/// </summary>
	void IncreaseGlobalVersion();

	/// <summary>
	/// 递增全局版本号（异步）
	/// </summary>
	/// <returns>异步任务</returns>
	Task IncreaseGlobalVersionAsync();

	/// <summary>
	/// 递增区域版本号（同步，多个值）
	/// </summary>
	/// <param name="propertyName">属性名称</param>
	/// <param name="propertyValues">属性值集合</param>
	void IncreaseAreaVersion(string propertyName, IEnumerable<object> propertyValues);

	/// <summary>
	/// 递增区域版本号（异步，多个值）
	/// </summary>
	/// <param name="propertyName">属性名称</param>
	/// <param name="propertyValues">属性值集合</param>
	/// <returns>异步任务</returns>
	Task IncreaseAreaVersionAsync(string propertyName, IEnumerable<object> propertyValues);

	/// <summary>
	/// 递增区域版本号（同步，单个值）
	/// </summary>
	/// <param name="propertyName">属性名称</param>
	/// <param name="propertyValue">属性值</param>
	void IncreaseAreaVersion(string propertyName, object propertyValue);

	/// <summary>
	/// 递增区域版本号（异步，单个值）
	/// </summary>
	/// <param name="propertyName">属性名称</param>
	/// <param name="propertyValue">属性值</param>
	/// <returns>异步任务</returns>
	Task IncreaseAreaVersionAsync(string propertyName, object propertyValue);

	/// <summary>
	/// 递增实体版本号（同步）
	/// </summary>
	/// <param name="entityId">实体ID</param>
	void IncreaseEntityCacheVersion(TKey entityId);

	/// <summary>
	/// 递增实体版本号（异步）
	/// </summary>
	/// <param name="entityId">实体ID</param>
	/// <returns>异步任务</returns>
	Task IncreaseEntityCacheVersionAsync(TKey entityId);

	/// <summary>
	/// 递增列表缓存版本号（同步）
	/// </summary>
	/// <param name="entity">实体对象</param>
	void IncreaseListCacheVersion(IEntity<TKey> entity);

	/// <summary>
	/// 递增列表缓存版本号（异步）
	/// </summary>
	/// <param name="entity">实体对象</param>
	/// <returns>异步任务</returns>
	Task IncreaseListCacheVersionAsync(IEntity<TKey> entity);
}